robloxfandomcom_tr-20200213-history
Modül:Iterator
local function vararg_any(...) return select('#', ...) ~= 0 end local function vararg_if(some, none, ...) if vararg_any(...) then return some(...) elseif none then return none() end end local function identity(...) return ... end local iterfuncs = {} local wrap local mt = { __index = function(t, k) return function(_, ...) return iterfuncsk(t.iter, ...) end end, __call = function(t) return t.iter() end, __tostring = function(t) return "" end } do -- call f for each item in iter iterfuncs.each = function(iter, f) repeat local done = false vararg_if(f, function() done = true end, iter()) until done end -- maps item... to f(item)... iterfuncs.map = function(iter, f) return wrap(function() return vararg_if(f, nil, iter()) end) end -- call f(item from it1, item from it2) for each iterfuncs.zip = function(iter, iter2, f) return wrap(function() return vararg_if(function(...) local n = select('#', ...) return vararg_if(function(...) if select('#', ...) > n then return ... end end, nil, ..., iter2()) end, nil, iter()) end) end -- keeps only items where f(item) is truthy iterfuncs.filter = function(iter, pred) pred = pred or identity local inner inner = function() return vararg_if(function(...) if pred(...) then return ... else return inner() end end, nil, iter()) end return wrap(inner) end -- returns true if pred(item) is true for any item iterfuncs.any = function(iter, pred) pred = pred or identity repeat local done = false local ok = vararg_if(pred, function() done = true end, iter()) if ok then return true end until done return false end -- returns true if pred(item) is true for all items iterfuncs.all = function(iter, pred) pred = pred or identity return not iterfuncs.any(iter, function(...) return not pred(...) end) end -- converts a 1-iterator to a list iterfuncs.to_list = function(iter) local res = {} iterfuncs.each(iter, function(...) local arity = select('#', ...) if arity ~= 1 then error(("Expected 1-iterator, got %d-iterator"):format(arity)) end local x = ... res#res+1 = x end) return res end -- converts a 2-iterator to a dict iterfuncs.to_dict = function(iter) local res = {} iterfuncs.each(iter, function(...) local arity = select('#', ...) if arity ~= 2 then error(("Expected 2-iterator, got %d-iterator"):format(arity)) end local k, v = ... resk = v end) return res end -- joins a 1-iterator iterfuncs.join = function(iter, val) return table.concat(iterfuncs.to_list(iter), val) end end local funcs = {} funcs.range = function(n) local i = 1 return wrap(function() if i < n then local cur = i i = i + 1 return cur else return end end) end funcs.pairs = function(t) local next = pairs(t) -- fix for scribuntu local k, v = next(t, k) return wrap(function() if k then local curk, curv = k, v k, v = next(t, k) return curk, curv end end) end funcs.values = function(t) return iterfuncs.map(funcs.pairs(t), function(k, v) return v end) end funcs.keys = function(t) return iterfuncs.map(funcs.pairs(t), function(k, v) return k end) end -- syntactic sugar - adds method to an iterator wrap = function(iter) if type(iter) 'function' then return setmetatable({iter=iter}, mt) elseif getmetatable(iter) mt then return iter elseif type(iter) 'table' then return funcs.values(iter) end end setmetatable(funcs, { __call = function(t, iter) return wrap(iter) end }) return funcs